﻿using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using WeChat.Common;
using System.Collections.Generic;
using DAL;
using System.Xml;
using System.IO;
using System.Text;
using WeChat.Common2;
using BLL;
using WeChat.JsSDK;
using ApplicationLog = DAL.ApplicationLog;

namespace WeChat
{
    public partial class _Default : System.Web.UI.Page
    {
        string result = "";//响应给用户的数据
        string after = "";//响应之后，后台处理数据
        SetBasicInfoBLL sb = new SetBasicInfoBLL();

        protected void Page_Load(object sender, EventArgs e)
        {

            #region //开发者模式验证接入部分
            if (Request.QueryString.Count == 4 
                && !string.IsNullOrEmpty(Request.QueryString["echoStr"]) 
                && !string.IsNullOrEmpty(Request.QueryString["signature"]) 
                && !string.IsNullOrEmpty(Request.QueryString["timestamp"]) 
                && !string.IsNullOrEmpty(Request.QueryString["nonce"]))
            {

                ApplicationLog.Write("接入验证开始");
                string vr_echoString = Request.QueryString["echoStr"];
                string vr_signature = Request.QueryString["signature"];
                string vr_timestamp = Request.QueryString["timestamp"];
                string vr_nonce = Request.QueryString["nonce"];
                if (WechatHelper.UrlVerify(vr_echoString, vr_signature, vr_timestamp, vr_nonce))
                {
                    Response.Write(vr_echoString);
                    Response.End();
                }
                return;
            }

            #endregion

            //接收微信服务器发送的数据
            /* 接收加密信息例子
             * POST /cgi-bin/wxpush? msg_signature=477715d11cdb4164915debcba66cb864d751f3e6&timestamp=1409659813&nonce=1372623149 HTTP/1.1
	            Host: qy.weixin.qq.com
                Content-Length: 613
             *
             * 	<xml>
	                <ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName>
	                <Encrypt><![CDATA[RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo+rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT+6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6+kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r+KqCKIw+3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0+rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS+/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl/T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==]]></Encrypt>
                </xml>
             */
            string msg_signature = Request.QueryString["msg_signature"];
            string timestamp = Request.QueryString["timestamp"];
            string nonce = Request.QueryString["nonce"];

            Stream stream = Request.InputStream;
            int len = (int)stream.Length;
            byte[] inputbytes = new byte[len];
            stream.Read(inputbytes, 0, len);
            stream.Close();
            string data = Encoding.GetEncoding("utf-8").GetString(inputbytes);
            //ApplicationLog.Write("接收到的xml:" + data);
            
            //解析加密数据
            string appid = Config.getAppID();//ConfigurationManager.AppSettings["appId"].ToString();
            string EncodingAESKey = Config.getEncodingAESKey();//ConfigurationManager.AppSettings["EncodingAESKey"].ToString();
            WXBizMsgCrypt wxcpt = new WXBizMsgCrypt("weixin", EncodingAESKey, appid);
            string sMsg = "";  //解析之后的明文
            int ret = 0;
            ret = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, data, ref sMsg);
            if (ret != 0)
            {
                ApplicationLog.Write("ERR: Decrypt fail, ret: " + ret);
                return;
            }

            //将接收到的数据转换为xml类型格式   偷懒写法，正式应该转成字典类型，或者XmlSerializer序列化成实体类型
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(sMsg);
            XmlNodeList xml = doc.DocumentElement.ChildNodes;
            string ToUserName = xml.Item(0).InnerText;  //开发者微信号
            string openid = xml.Item(1).InnerText;      //发送方帐号（用户OpenID）
            string CreateTime = xml.Item(2).InnerText;
            string MsgType = xml.Item(3).InnerText;
            //对返回xml类型判断
            switch (MsgType)
            {
                //接收到的为事件类型
                case "event":
                    string Event = xml.Item(4).InnerText;
                    switch (Event)
                    {
                        //用户关注事件
                        case "subscribe":              
                            string content = sb.getInfo("用户关注消息");
                            result = ReturnTextXml.returnText(openid, ToUserName,  content);
                            ApplicationLog.Write("有新的用户关注:" + openid);
                            after = "subscribe";
                            break;
                        //菜单点击事件（方法写在下方↓）
                        case "CLICK":                                      
                            string key = xml.Item(5).InnerText;            //事件KEY值（与自定义菜单接口中KEY值对应）
                            this.verifyClick(key,openid,ToUserName);
                            break;
                        //菜单跳转事件
                        case "view":                  
                            break;
                        //事件推送群发结果 
                        case "MASSSENDJOBFINISH":  
                            string MsgID = xml.Item(5).InnerText;          //群发的消息ID
                            string Status = xml.Item(6).InnerText;         //群发的结果
                            string TotalCount = xml.Item(7).InnerText;     //group_id下粉丝数；或者openid_list中的粉丝数
                            string FilterCount = xml.Item(8).InnerText;    //过滤后，准备发送的粉丝数
                            string SentCount = xml.Item(9).InnerText;      //发送成功的粉丝数
                            string ErrorCount = xml.Item(10).InnerText;    //发送失败的粉丝数
                            bool o = saveMassMsg(ToUserName, openid, CreateTime, MsgType, Event, MsgID, Status, TotalCount, FilterCount, SentCount, ErrorCount);
                            if (o) ApplicationLog.Write("群发消息结果:" + Status);
                            result = "success";
                            break;
                        //用户取消关注事件
                        case "unsubscribe":           
                            after = "unsubscribe";
                            break;
                        default:
                            break;
                    }
                    break;
                //接收到的数据为文本类型
                case "text":   
                    //用户发送文本消息，则转入客服连接      
                    string contents = xml.Item(4).InnerText;
                    //ApplicationLog.Write("用户发送文本:" + contents);
                    XmlDocument xl = new XmlDocument();
                    xl.Load(MapPath("Duokefu.xml"));
                    XmlNodeList xmls = xl.DocumentElement.ChildNodes;
                    xmls[0].AppendChild(xl.CreateCDataSection(openid));
                    xmls[1].AppendChild(xl.CreateCDataSection(ToUserName));
                    xmls[2].InnerText = GetSdkParams.getTimestamp();
                    xmls[3].AppendChild(xl.CreateCDataSection("transfer_customer_service"));
                    //ApplicationLog.Write("进入客服转接");
                    result = xl.InnerXml;
                break;
                default:
                    break;
            }
            //回复用户消息也需要加密和拼接xml字符串
            string sEncryptMsg = ""; //xml格式的密文
            if (result != "")        //如果直接返回空串，则不需要加密
            {
                ret = wxcpt.EncryptMsg(result, GetSdkParams.getTimestamp(), nonce, ref sEncryptMsg);
                //ApplicationLog.Write("发送给用户的xml:" + result);
            }
            Response.ContentType = "text/plain";
            Response.Output.Write(sEncryptMsg);
            
            //ApplicationLog.Write("发送给用户的加密文:" + sEncryptMsg);

            //响应之后，后台处理数据
            switch (after)
            {
                case "subscribe":
                    subs(openid);
                    break;
                case "unsubscribe":
                    unSubs(openid);
                    break;
                //连接客服菜单
                case "Customer_service":  
                    string state = KefuSendMsg.getKefuStates();//查询客服在线状态
                    if (state == "") { state = "对不起，当前无客服在线/可怜\n"; }
                    string content = sb.getInfo("连接客服消息") + Config.getKefuReturn(state);
                    string res = KefuSendMsg.sendText(openid, content);
                    if (!res.Trim().Contains("\"errcode\":0"))
                    {
                        ApplicationLog.Write("客服推送消息失败！，返回:" + res);
                    }
                    break;
            }
        }

        //用户关注事件  根据openid发送请求得到用户信息保存至数据库
        public void subs(string openid)
        {
            GetUsers gu = new GetUsers();
            string m = gu.getUserInfo(openid);
            ApplicationLog.Write(m);
        }

        //用户取消关注事件
        public void unSubs(string openid)
        {
            SubscribesBLL sb = new SubscribesBLL();
            bool o = sb.delSubsUser(openid);
            if (o)
            {
                ApplicationLog.Write("用户取消关注："+openid);
            }
        }

        //菜单点击事件
        private void verifyClick(string key, string openid, string ToUserName)
        {
            string media_id = "";//发送客服消息的素材ID
            string res = "";//发送客服消息返回数据

            //如果点击公司资讯菜单，则直接响应，点击其他菜单则先判断是否绑定
            switch (key)
            {
                //公司简介
                case "Introductions":       
                    media_id = sb.getInfo("公司简介");
                    res = KefuSendMsg.sendMsg(openid, media_id);
                    if (res.Trim().Contains("\"errcode\":0"))
                    {
                        //ApplicationLog.Write("客服推送消息成功！，media_id:" + media_id);
                    }
                    else
                    {
                        ApplicationLog.Write("客服推送公司简介失败！，返回:" + res);
                    }
                    break;
                //最新资讯
                case "Information_pushed":      
                    media_id = sb.getInfo("最新资讯");
                    res = KefuSendMsg.sendMsg(openid,media_id);
                    if (!res.Trim().Contains("\"errcode\":0"))
                    {
                        ApplicationLog.Write("客服推送最新资讯失败！，返回:" + res);
                    }
                    break;
                //连接客服
                case "Customer_service":
                    after = "Customer_service";
                    break;  
                default:
                    break;
            }
        }

        //消息群发事件，接收群发消息响应,保存至数据库
        private bool saveMassMsg(string ToUserName, string FromUserName, string CreateTime, string msgType, string events, string msgID, string status, string totalCount, string filterCount, string sentCount, string errorCount)
        {
            MediaBLL md = new MediaBLL();
            string time = FormatTimeBLL.formatTime(CreateTime);
            bool o = md.addMassMsg(ToUserName, FromUserName, time, msgType, events, Int32.Parse(msgID), status, Int32.Parse(totalCount), Int32.Parse(filterCount), Int32.Parse(sentCount), Int32.Parse(errorCount));
            return o;
        }

        //验证是否绑定账号
        //private bool verifyBindid(string openid, string ToUserName, string CreateTime)
        //{
        //    bool m = new BindIdBLL().verifyId(openid);
        //    if (!m)
        //    {
        //        //如果用户未绑定账号，发送消息提醒绑定
        //        string content = "您还未绑定账号，无法查询相关内容。<a href=\"http://wechat.jocat.com/Binding.aspx?openid=" + openid + "\">点此绑定账号</a> ";
        //        //string content = "<a href=\"http://wechat.jocat.com/JsSDK/WxConfig.aspx\">测试jssdk</a>";
        //        result = ReturnTextXml.returnText(openid, ToUserName, content);
        //        return false;
        //    }
        //    return true;
        //}
        
    }
}


